#include "comm/znx_chash.h"
#include "comm/znx_mem.h"
#include <stdlib.h>

void test1()
{

    znx_chash_t *chash = znx_chash_create(100);

    znx_str_t s1 = {.data= (u_char *)"aaa", .len = 3};
    znx_str_t s2 = {.data= (u_char *)"bbb", .len = 3};
    znx_str_t s3 = {.data= (u_char *)"ccc", .len = 3};
    znx_str_t s4 = {.data= (u_char *)"ddd", .len = 3};
    znx_str_t s5 = {.data= (u_char *)"eee", .len = 3};

    znx_chash_add_node(chash, &s1, "aaa", 1);
    znx_chash_add_node(chash, &s2, "bbb", 1);
    znx_chash_add_node(chash, &s3, "ccc", 1);
    znx_chash_add_node(chash, &s4, "ddd", 1);
    znx_chash_add_node(chash, &s5, "eee", 1);
    znx_chash_build(chash);

    char buf[64];
    for (int i = 0; i < 1000; i++) {
        sprintf(buf, "%d", i);
        znx_str_t key = {.data=(u_char *)buf, .len=(size_t)strlen(buf)};

        znx_chash_result_t result = znx_chash_get(chash, &key, 0, NULL, NULL, ZNX_FALSE);

        if (result.server == NULL) {
            DD_FATAL("unexcept result");
        }
        DD("key: %d, data: %s", i, (char *)result.server);
    }

    znx_chash_destroy(chash);
}

znx_bool_t znx_chash_node_check(znx_chash_node_t *node, void *user_data)
{
    if (node->key.len == 3
        && znx_strncmp(node->key.data, "aaa", 3) == 0) {
        return ZNX_FALSE;
    }

    return ZNX_TRUE;
}

void test2()
{
    znx_chash_t *chash = znx_chash_create(100);

    znx_str_t s1 = {.data= (u_char *)"aaa", .len = 3};
    znx_str_t s2 = {.data= (u_char *)"bbb", .len = 3};
    znx_str_t s3 = {.data= (u_char *)"ccc", .len = 3};
    znx_str_t s4 = {.data= (u_char *)"ddd", .len = 3};
    znx_str_t s5 = {.data= (u_char *)"eee", .len = 3};

    znx_chash_add_node(chash, &s1, (u_char *)"aaa", 1);
    znx_chash_add_node(chash, &s2, (u_char *)"bbb", 1);
    znx_chash_add_node(chash, &s3, (u_char *)"ccc", 1);
    znx_chash_add_node(chash, &s4, (u_char *)"ddd", 1);
    znx_chash_add_node(chash, &s5, (u_char *)"eee", 1);
    znx_chash_build(chash);

    char buf[64];
    for (int i = 0; i < 1000; i++) {
        sprintf(buf, "%d", i);
        znx_str_t key = {.data=(u_char *)buf, .len=(size_t)strlen(buf)};
        znx_chash_result_t result = znx_chash_get(chash, &key, 0, znx_chash_node_check, NULL, ZNX_FALSE);
        if (result.server == NULL) {
            continue;
        }

        if (strncmp(result.server, "aaa", 3) == 0) {
            DD_FATAL("unexcept result");
        }

        DD("key: %d, data: %s", i, (char *)result.server);
    }

    znx_chash_destroy(chash);
}

void test3()
{
    znx_chash_t *chash = znx_chash_create(100);

    znx_chash_build(chash);
    znx_str_t key = {.data= (u_char *)"aaa", .len = 3};
    znx_chash_result_t result = znx_chash_get(chash, &key, 0, NULL, NULL, ZNX_FALSE);
    if (result.server != NULL) {
        DD_FATAL("unexcept result");
    }

    znx_chash_destroy(chash);
}

znx_bool_t znx_test_checker(znx_chash_node_t *node, void *user_data)
{
    (void)node;
    return ZNX_FALSE;
}

void test4()
{
    znx_chash_t *chash = znx_chash_create(100);

    znx_str_t s1 = {.data= (u_char *)"aaa", .len = 3};
    znx_str_t s2 = {.data= (u_char *)"bbb", .len = 3};
    znx_str_t s3 = {.data= (u_char *)"ccc", .len = 3};
    znx_str_t s4 = {.data= (u_char *)"ddd", .len = 3};
    znx_str_t s5 = {.data= (u_char *)"eee", .len = 3};

    znx_chash_add_node(chash, &s1, (u_char *)"aaa", 1);
    znx_chash_add_node(chash, &s2, (u_char *)"bbb", 1);
    znx_chash_add_node(chash, &s3, (u_char *)"ccc", 1);
    znx_chash_add_node(chash, &s4, (u_char *)"ddd", 1);
    znx_chash_add_node(chash, &s5, (u_char *)"eee", 1);
    znx_chash_build(chash);

    DD("######## test4 ########");
    for (int i = 0; i < 10000; i++) {
        znx_str_t key = {.data= (u_char *)"aaa", .len = 3};
        znx_chash_result_t result = znx_chash_get(chash, &key, 0, znx_test_checker, NULL, ZNX_TRUE);
        if (result.server == NULL) {
            DD_FATAL("unexcept result");
        }

        DD("test4:  %s", (char *)result.server);
    }

    znx_chash_destroy(chash);
}


void test5()
{
    znx_chash_t *chash = znx_chash_create(100);

    znx_str_t s1 = {.data= (u_char *)"aaa", .len = 3};
    znx_str_t s2 = {.data= (u_char *)"bbb", .len = 3};
    znx_str_t s3 = {.data= (u_char *)"ccc", .len = 3};
    znx_str_t s4 = {.data= (u_char *)"ddd", .len = 3};
    znx_str_t s5 = {.data= (u_char *)"eee", .len = 3};

    znx_chash_add_node(chash, &s1, (u_char *)"aaa", 1);
    znx_chash_add_node(chash, &s2, (u_char *)"bbb", 1);
    znx_chash_add_node(chash, &s3, (u_char *)"ccc", 1);
    znx_chash_add_node(chash, &s4, (u_char *)"ddd", 1);
    znx_chash_add_node(chash, &s5, (u_char *)"eee", 1);
    znx_chash_build(chash);

    znx_str_t key = {.data= (u_char *)"zzz", .len = 3};
    znx_chash_result_t result = znx_chash_get(chash, &key, -1, znx_test_checker, NULL, ZNX_TRUE);
    if (result.server == NULL || result.balance_server != NULL) {
        DD_FATAL("unexcept result");
    }

    znx_chash_destroy(chash);
}


void test6()
{
    znx_chash_t *chash = znx_chash_create(100);

    znx_str_t s1 = {.data= (u_char *)"aaa", .len = 3};
    znx_str_t s2 = {.data= (u_char *)"bbb", .len = 3};
    znx_str_t s3 = {.data= (u_char *)"ccc", .len = 3};
    znx_str_t s4 = {.data= (u_char *)"ddd", .len = 3};
    znx_str_t s5 = {.data= (u_char *)"eee", .len = 3};

    znx_chash_add_node(chash, &s1, (u_char *)"aaa", 1);
    znx_chash_add_node(chash, &s2, (u_char *)"bbb", 1);
    znx_chash_add_node(chash, &s3, (u_char *)"ccc", 1);
    znx_chash_add_node(chash, &s4, (u_char *)"ddd", 1);
    znx_chash_add_node(chash, &s5, (u_char *)"eee", 1);
    znx_chash_build(chash);

    znx_str_t key = {.data= (u_char *)"zzz", .len = 3};
    znx_chash_result_t result = znx_chash_get(chash, &key, 6, NULL, NULL, ZNX_TRUE);
    if (result.server == NULL || result.balance_server == NULL) {
        DD_FATAL("unexcept result");
    }

    DD("test6:  %s, %s", (char *)result.server, (char *)result.balance_server);

    znx_chash_destroy(chash);
}


int main()
{
    test1();

    test2();

    test3();

    test4();

    test5();

    test6();

    return 0;
}
